#!/bin/bash
# ThingsBoard 备份恢复共用脚本
# 版本: 1.0.0
# 注意: 该脚本使用UTF-8编码，请确保编辑器使用正确的编码方式

# 获取脚本所在目录的绝对路径
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)

# 根据脚本目录计算项目根目录路径
if [[ "$SCRIPT_DIR" == */scripts/* ]]; then
  # 如果脚本位于scripts目录或子目录中
  PROJECT_ROOT=$(echo "$SCRIPT_DIR" | sed 's|\(.*\)/scripts.*|\1|')
else
  # 否则假设当前目录是项目根目录
  PROJECT_ROOT=$(pwd)
fi

# 配置文件路径
CONFIG_FILE="$PROJECT_ROOT/config/backup_env.conf"

# 加载配置文件
if [ -f "$CONFIG_FILE" ]; then
  source "$CONFIG_FILE"
else
  echo "错误: 配置文件不存在: $CONFIG_FILE"
  exit 1
fi

# 确保目录存在
check_directory() {
  local dir="$1"
  if [ ! -d "$dir" ]; then
    echo "创建目录: $dir"
    mkdir -p "$dir" || { echo "错误: 无法创建目录 $dir"; exit 1; }
  fi
}

# 确保日志目录存在
check_directory "$LOG_DIR"

# 步骤计数器
STEP=0

# 获取下一个步骤计数
next_step() {
  STEP=$((STEP+1))
  echo $STEP
}

# 日志文件
LOG_FILE="$LOG_DIR/$(basename "${BASH_SOURCE[0]}" .sh)_$(date '+%Y%m%d_%H%M%S').log"
touch "$LOG_FILE" || { echo "错误: 无法创建日志文件 $LOG_FILE"; exit 1; }

# 日志函数
log_info() {
  local message="$1"
  local step="${2:-}"
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

  if [ -n "$step" ]; then
    echo "[$timestamp] [INFO] [步骤 $step] $message"
    echo "[$timestamp] [INFO] [步骤 $step] $message" >> "$LOG_FILE"
  else
    echo "[$timestamp] [INFO] $message"
    echo "[$timestamp] [INFO] $message" >> "$LOG_FILE"
  fi
}

log_success() {
  local message="$1"
  local step="${2:-}"
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

  if [ -n "$step" ]; then
    echo -e "[$timestamp] [\033[32mSUCCESS\033[0m] [步骤 $step] $message"
    echo "[$timestamp] [SUCCESS] [步骤 $step] $message" >> "$LOG_FILE"
  else
    echo -e "[$timestamp] [\033[32mSUCCESS\033[0m] $message"
    echo "[$timestamp] [SUCCESS] $message" >> "$LOG_FILE"
  fi
}

log_warn() {
  local message="$1"
  local step="${2:-}"
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

  if [ -n "$step" ]; then
    echo -e "[$timestamp] [\033[33mWARNING\033[0m] [步骤 $step] $message"
    echo "[$timestamp] [WARNING] [步骤 $step] $message" >> "$LOG_FILE"
  else
    echo -e "[$timestamp] [\033[33mWARNING\033[0m] $message"
    echo "[$timestamp] [WARNING] $message" >> "$LOG_FILE"
  fi
}

log_error() {
  local message="$1"
  local step="${2:-}"
  local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

  if [ -n "$step" ]; then
    echo -e "[$timestamp] [\033[31mERROR\033[0m] [步骤 $step] $message" >&2
    echo "[$timestamp] [ERROR] [步骤 $step] $message" >> "$LOG_FILE"
  else
    echo -e "[$timestamp] [\033[31mERROR\033[0m] $message" >&2
    echo "[$timestamp] [ERROR] $message" >> "$LOG_FILE"
  fi
}

log_debug() {
  if [ "$DEBUG_MODE" = "true" ]; then
    local message="$1"
    local step="${2:-}"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    if [ -n "$step" ]; then
      echo -e "[$timestamp] [\033[36mDEBUG\033[0m] [步骤 $step] $message"
      echo "[$timestamp] [DEBUG] [步骤 $step] $message" >> "$LOG_FILE"
    else
      echo -e "[$timestamp] [\033[36mDEBUG\033[0m] $message"
      echo "[$timestamp] [DEBUG] $message" >> "$LOG_FILE"
    fi
  fi
}

# 发送通知
send_notification() {
  local subject="$1"
  local message="$2"

  if [ "$ENABLE_NOTIFICATIONS" = "true" ]; then
    # 计算通知脚本路径
    local notification_script="$SCRIPT_DIR/monitoring/notification.sh"
    if [ -f "$notification_script" ]; then
      bash "$notification_script" -s "$subject" -m "$message" -l "info"
    else
      log_warn "无法找到通知脚本: $notification_script"
    fi
    return $?
  fi

  return 0
}

# 错误处理
handle_error() {
  local code="$1"
  local message="$2"
  local step="${3:-}"

  if [ -n "$step" ]; then
    log_error "$message" "$step"
    send_notification "ThingsBoard备份/恢复失败" "步骤 $step: $message"
  else
    log_error "$message"
    send_notification "ThingsBoard备份/恢复失败" "$message"
  fi

  exit "$code"
}

# 检查依赖项
check_dependencies() {
  local step="$1"

  log_info "检查系统依赖..." "$step"

  # 检查必要的命令
  local commands=("tar" "jq" "curl" "grep")
  for cmd in "${commands[@]}"; do
    if ! command -v "$cmd" &> /dev/null; then
      log_warn "命令 $cmd 未找到，尝试安装..." "$step"
      apt-get update && apt-get install -y "$cmd" || handle_error 1 "无法安装 $cmd" "$step"
    fi
  done

  # 检查WAL-G
  if ! command -v wal-g &> /dev/null; then
    log_warn "WAL-G未找到，需要安装WAL-G才能进行备份/恢复" "$step"
    log_info "请运行 'sudo bash scripts/install/install_walg.sh' 安装WAL-G" "$step"
  fi

  # 如果使用Docker，检查docker命令
  if [ "$USE_DOCKER" = "true" ]; then
    if ! command -v docker &> /dev/null; then
      handle_error 2 "Docker未安装，请先安装Docker" "$step"
    fi
  fi

  log_success "所有依赖项检查通过" "$step"
}

# 检查PostgreSQL是否可用
check_postgres_available() {
  local step="${1:-"1"}"

  log_info "检查PostgreSQL可用性..." "$step"

  if [ "$USE_DOCKER" = "true" ]; then
    # 检查容器是否运行
    if ! docker ps | grep -q "$POSTGRES_CONTAINER_NAME"; then
      log_info "PostgreSQL容器未运行，尝试启动..." "$step"
      docker start "$POSTGRES_CONTAINER_NAME"
      sleep 5

      if ! docker ps | grep -q "$POSTGRES_CONTAINER_NAME"; then
        handle_error 3 "无法启动PostgreSQL容器" "$step"
      fi
    fi

    # 检查可以连接到PostgreSQL
    if ! docker exec "$POSTGRES_CONTAINER_NAME" psql -U "$POSTGRES_SUPERUSER" -c "SELECT 1" > /dev/null 2>&1; then
      handle_error 4 "无法连接到PostgreSQL数据库" "$step"
    fi
  else
    # 检查本地PostgreSQL服务
    if ! systemctl is-active postgresql &>/dev/null; then
      log_info "PostgreSQL服务未运行，尝试启动..." "$step"
      systemctl start postgresql
      sleep 5

      if ! systemctl is-active postgresql &>/dev/null; then
        handle_error 5 "无法启动PostgreSQL服务" "$step"
      fi
    fi

    # 检查可以连接到PostgreSQL
    if ! PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_SUPERUSER" -h localhost -c "SELECT 1" > /dev/null 2>&1; then
      handle_error 6 "无法连接到PostgreSQL数据库" "$step"
    fi
  fi

  log_success "PostgreSQL可用性检查通过" "$step"
}

# 检查ThingsBoard服务
check_thingsboard_service() {
  if [ "$SERVICE_MODE" = "true" ]; then
    if systemctl is-active thingsboard &>/dev/null; then
      return 0
    else
      return 1
    fi
  else
    # 后续可添加非服务模式的检查
    return 0
  fi
}

# 停止ThingsBoard服务
stop_thingsboard() {
  if [ "$SERVICE_MODE" = "true" ]; then
    if systemctl is-active thingsboard &>/dev/null; then
      log_info "停止ThingsBoard服务..."
      systemctl stop thingsboard
      sleep 5

      if systemctl is-active thingsboard &>/dev/null; then
        log_warn "无法正常停止ThingsBoard服务，尝试强制停止..."
        systemctl kill thingsboard
        sleep 5
      fi

      if systemctl is-active thingsboard &>/dev/null; then
        handle_error 7 "无法停止ThingsBoard服务"
      else
        log_success "ThingsBoard服务已停止"
      fi
    else
      log_info "ThingsBoard服务已处于停止状态"
    fi
  else
    # 后续可添加非服务模式的停止逻辑
    log_info "ThingsBoard未作为服务运行，跳过停止"
  fi
}

# 检查环境
check_environment() {
  log_info "加载配置文件: $CONFIG_FILE"
  check_dependencies "0"
  check_postgres_available "0"

  # 确保备份目录存在
  check_directory "$BACKUP_BASE_DIR"
  check_directory "$BACKUP_BASE_DIR/full"
  check_directory "$BACKUP_BASE_DIR/diff"
  check_directory "$RECOVERY_TEMP_DIR"

  # 导出时间戳变量，供其他脚本使用
  export TIMESTAMP=$(date +%Y%m%d_%H%M%S)

  log_success "环境检查完成"
}

# 向控制台和日志输出公共头信息
log_info "========================================================"
log_info "ThingsBoard 备份恢复脚本 - 共用模块加载完成"
log_info "========================================================"
log_info "项目根目录: $PROJECT_ROOT"
log_info "配置文件已加载: $CONFIG_FILE"
